package com.darren.framework.http;


import org.apache.commons.io.IOUtils;

import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Collections;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;

/**
 * 自己包装的Request,用于修改参数等功能
 *
 * @author: 周金涛
 * @date: 2019-11-21 10:49:40
 */
public class CustomRequestWrapper extends HttpServletRequestWrapper {

    private ByteArrayOutputStream cacheBytes;

    // 用于存储请求参数
    private Map<String, String[]> params = new HashMap<String, String[]>();

    public CustomRequestWrapper(HttpServletRequest request) throws IOException {
        super(request);
        extraParams(request);
        cacheBytes = new ByteArrayOutputStream();
        IOUtils.copy(super.getInputStream(), cacheBytes);
    }

    /**
     * 添加参数到map中
     *
     * @param request
     */
    private void extraParams(HttpServletRequest request) {
        Map<String, Object> parameterMap = new HashMap<String, Object>(request.getParameterMap());
        if (parameterMap != null) {
            for (Map.Entry<String, Object> entry : parameterMap.entrySet()) {
                setParameter(entry.getKey(), entry.getValue());
            }
        }
    }

    /**
     * 添加参数
     *
     * @param name
     * @param value
     */
    public void setParameter(String name, Object value) {
        if (value == null) {
            params.put(name, null);
        } else if (value instanceof String[]) {
            params.put(name, (String[]) value);
        } else if (value instanceof String) {
            params.put(name, new String[]{(String) value});
        } else {
            params.put(name, new String[]{String.valueOf(value)});
        }
    }

    /**
     * 根据参数名，获取参数值
     * 获取前台表单单个元素name对应的value值
     *
     * @param name 参数名
     * @return 参数值
     */
    @Override
    public String getParameter(String name) {
        Object value = params.get(name);
        if (value == null) {
            return null;
        } else if (value instanceof String[]) {
            String[] stringArray = (String[]) value;
            if (stringArray.length > 0) {
                return stringArray[0];
            }
            return null;
        } else if (value instanceof String) {
            return (String) value;
        } else {
            return value.toString();
        }
    }

    /**
     * 获取前台表单多个标签同名name对应的所有value值
     *
     * @param name
     * @return
     */
    @Override
    public String[] getParameterValues(String name) {
        Object value = params.get(name);
        if (value == null) {
            return null;
        } else if (value instanceof String[]) {
            return (String[]) value;
        } else if (value instanceof String) {
            return new String[]{(String) value};
        } else {
            return new String[]{value.toString()};
        }
    }


    /**
     * 获取请求参数
     *
     * @return
     */
    @Override
    public Enumeration<String> getParameterNames() {
        return Collections.enumeration(this.params.keySet());
    }


    @Override
    public ServletInputStream getInputStream() throws IOException {
        return new CacheServletInputStream();
    }


    @Override
    public BufferedReader getReader() throws IOException {
        return new BufferedReader(new InputStreamReader(getInputStream(), "UTF-8"));
    }

    class CacheServletInputStream extends ServletInputStream {

        private ByteArrayInputStream byteArrayInputStream;

        public CacheServletInputStream() {
            byteArrayInputStream = new ByteArrayInputStream(cacheBytes.toByteArray());
        }

        @Override
        public int read() throws IOException {
            return byteArrayInputStream.read();
        }

        @Override
        public void close() throws IOException {
            super.close();
            byteArrayInputStream.close();
            cacheBytes.close();
        }
    }
}
